#include "mystdio.h"
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <malloc.h>
#include <unistd.h>
#include <assert.h>



  //打开文件的方式"r" "w" "a"
MY_FILE* my_fopen(const char* path, const char* mode)
{
    //1.识别标识位
      int flag = 0;
  if(strcmp(mode, "r") == 0) flag |= O_RDONLY;
  else if(strcmp(mode, "w") == 0) flag |= (O_WRONLY | O_CREAT | O_TRUNC);
  else if(strcmp(mode, "a") == 0) flag |= (O_WRONLY | O_CREAT | O_APPEND);
  else{
      //....
  }

  //2.打开文件
  int fd = 0;
  if(flag & O_CREAT)
  {
    //说明文件之前并没有存在，是新创建的
    fd = open(path, flag, 0666);//注意这个权限是受umask影响的
  }
  else
  {
      fd = open(path, flag);//直接打开就好
  }
    
  if(fd < 0) return NULL;//打开文件失败

  //3.给用户返回文件指针，先创建再返回
  MY_FILE* mfp = (MY_FILE*)malloc(sizeof(MY_FILE));
  if(mfp == NULL) 
  {
    close(fd);
    return NULL;//文件指针创建失败--内存不足,关闭打开的文件描述符
  }

  //sucess--初始化
  mfp->fd = fd;
  mfp->flags = BUF_LINE;//默认实现的是行缓冲
  memset(mfp->outputbuffer, '\0', sizeof(mfp->outputbuffer));
  mfp->current = 0;

  //5.返回打开的文件
  return mfp;

}

int my_fflush(MY_FILE* fp)
{
  assert(fp);

  //通过调用系统调用接口来想OS的文件系统缓冲区中写入
  write(fp->fd, fp->outputbuffer, fp->current);
  fp->current = 0;

  fsync(fp->fd);
  
  return 0;
}

size_t my_fwrite(const void* ptr, size_t size, size_t num, MY_FILE* stream)
{
  // 1. 缓冲区如果已经满了，就直接写入
    if(stream->current == NUM) my_fflush(stream);

    // 2. 根据缓冲区剩余情况，进行数据拷贝即可
    size_t user_size = size * num;//用户的数据大小
    size_t my_size = NUM - stream->current; //缓冲区中剩余数据的大小

    size_t writen = 0;//返回值，写入的字节数
    if(my_size >= user_size)
    {
        memcpy(stream->outputbuffer + stream->current, ptr, user_size);
        //3.更新缓冲区数据的大小
        stream->current += user_size;
        writen = user_size;

    }
    else
    {
      //不满足的时候，我们直考虑将缓冲区写满后写入，剩下的用户数据就丢弃
        memcpy(stream->outputbuffer + stream->current, ptr, my_size);
        //3.更新缓冲区数据的大小
        stream->current += my_size;
        writen = my_size;
    }

    //4.将数据写入缓冲区之后我们开始考虑刷新缓冲区的问题-----行缓冲
    
    if(stream->flags & BUF_NULL)
    {
        //无缓冲
    }
    else if(stream->flags & BUF_LINE)
    {
      //最后一个字符是'\n'的话就去写入(刷新缓冲区)
      if(stream->outputbuffer[stream->current-1] == '\n') my_fflush(stream);
    }
    else
    {
      //全缓冲
      if(stream->current == NUM) my_fflush(stream);
    }

    //返回写入的字节数
    return writen;

}

int my_fclose(MY_FILE* fp)
{
  assert(fp);
  
  if(fp->current > 0) my_fflush(fp);

  close(fp->fd);

  fp->current = 0;
  free(fp);
  fp = NULL;

  return 0;
}
